{
 "cells": [
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "pycharm": {
     "is_executing": true
    }
   },
   "outputs": [],
   "source": [
    "import time\n",
    "T1 = time.process_time()\n",
    "\n",
    "import pandas as pd\n",
    "\n",
    "import numpy as np\n",
    "my_seed = 2017\n",
    "np.random.seed(my_seed)\n",
    "\n",
    "import random \n",
    "random.seed(my_seed)\n",
    "\n",
    "import tensorflow as tf\n",
    "tf.random.set_seed(my_seed)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 50,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/html": [
       "<div>\n",
       "<style scoped>\n",
       "    .dataframe tbody tr th:only-of-type {\n",
       "        vertical-align: middle;\n",
       "    }\n",
       "\n",
       "    .dataframe tbody tr th {\n",
       "        vertical-align: top;\n",
       "    }\n",
       "\n",
       "    .dataframe thead th {\n",
       "        text-align: right;\n",
       "    }\n",
       "</style>\n",
       "<table border=\"1\" class=\"dataframe\">\n",
       "  <thead>\n",
       "    <tr style=\"text-align: right;\">\n",
       "      <th></th>\n",
       "      <th>timestamp</th>\n",
       "      <th>link_id</th>\n",
       "      <th>throughput</th>\n",
       "      <th>delay</th>\n",
       "      <th>jitter</th>\n",
       "      <th>loss</th>\n",
       "      <th>入端口</th>\n",
       "      <th>出端口</th>\n",
       "      <th>组合</th>\n",
       "    </tr>\n",
       "  </thead>\n",
       "  <tbody>\n",
       "    <tr>\n",
       "      <th>0</th>\n",
       "      <td>00:56:56.600000</td>\n",
       "      <td>4-3-2-5</td>\n",
       "      <td>0</td>\n",
       "      <td>1.355648</td>\n",
       "      <td>1.355648</td>\n",
       "      <td>0.0</td>\n",
       "      <td>4</td>\n",
       "      <td>5</td>\n",
       "      <td>45</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>1</th>\n",
       "      <td>00:57:09.600000</td>\n",
       "      <td>4-3-2-5</td>\n",
       "      <td>3200</td>\n",
       "      <td>1.294017</td>\n",
       "      <td>0.061631</td>\n",
       "      <td>0.0</td>\n",
       "      <td>4</td>\n",
       "      <td>5</td>\n",
       "      <td>45</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>2</th>\n",
       "      <td>00:57:36.700000</td>\n",
       "      <td>4-3-2-5</td>\n",
       "      <td>0</td>\n",
       "      <td>1.390100</td>\n",
       "      <td>1.390100</td>\n",
       "      <td>0.0</td>\n",
       "      <td>4</td>\n",
       "      <td>5</td>\n",
       "      <td>45</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>3</th>\n",
       "      <td>00:57:49.700000</td>\n",
       "      <td>4-3-2-5</td>\n",
       "      <td>4930</td>\n",
       "      <td>1.552820</td>\n",
       "      <td>0.162721</td>\n",
       "      <td>0.0</td>\n",
       "      <td>4</td>\n",
       "      <td>5</td>\n",
       "      <td>45</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>4</th>\n",
       "      <td>00:58:02.700000</td>\n",
       "      <td>4-3-2-5</td>\n",
       "      <td>753</td>\n",
       "      <td>1.465440</td>\n",
       "      <td>0.087380</td>\n",
       "      <td>0.0</td>\n",
       "      <td>4</td>\n",
       "      <td>5</td>\n",
       "      <td>45</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>5</th>\n",
       "      <td>00:58:15.700000</td>\n",
       "      <td>4-3-2-5</td>\n",
       "      <td>705</td>\n",
       "      <td>1.517892</td>\n",
       "      <td>0.052452</td>\n",
       "      <td>0.0</td>\n",
       "      <td>4</td>\n",
       "      <td>5</td>\n",
       "      <td>45</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>6</th>\n",
       "      <td>00:58:28.700000</td>\n",
       "      <td>4-3-2-5</td>\n",
       "      <td>720</td>\n",
       "      <td>1.559973</td>\n",
       "      <td>0.042081</td>\n",
       "      <td>0.0</td>\n",
       "      <td>4</td>\n",
       "      <td>5</td>\n",
       "      <td>45</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>7</th>\n",
       "      <td>00:58:41.800000</td>\n",
       "      <td>4-3-2-5</td>\n",
       "      <td>772</td>\n",
       "      <td>3.505945</td>\n",
       "      <td>1.945972</td>\n",
       "      <td>0.0</td>\n",
       "      <td>4</td>\n",
       "      <td>5</td>\n",
       "      <td>45</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>8</th>\n",
       "      <td>00:58:54.800000</td>\n",
       "      <td>4-3-2-5</td>\n",
       "      <td>672</td>\n",
       "      <td>0.675440</td>\n",
       "      <td>2.830505</td>\n",
       "      <td>0.0</td>\n",
       "      <td>4</td>\n",
       "      <td>5</td>\n",
       "      <td>45</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>9</th>\n",
       "      <td>00:59:07.800000</td>\n",
       "      <td>4-3-2-5</td>\n",
       "      <td>1668</td>\n",
       "      <td>7.353544</td>\n",
       "      <td>6.678104</td>\n",
       "      <td>0.0</td>\n",
       "      <td>4</td>\n",
       "      <td>5</td>\n",
       "      <td>45</td>\n",
       "    </tr>\n",
       "  </tbody>\n",
       "</table>\n",
       "</div>"
      ],
      "text/plain": [
       "         timestamp  link_id  throughput     delay    jitter  loss  入端口  出端口  \\\n",
       "0  00:56:56.600000  4-3-2-5           0  1.355648  1.355648   0.0    4    5   \n",
       "1  00:57:09.600000  4-3-2-5        3200  1.294017  0.061631   0.0    4    5   \n",
       "2  00:57:36.700000  4-3-2-5           0  1.390100  1.390100   0.0    4    5   \n",
       "3  00:57:49.700000  4-3-2-5        4930  1.552820  0.162721   0.0    4    5   \n",
       "4  00:58:02.700000  4-3-2-5         753  1.465440  0.087380   0.0    4    5   \n",
       "5  00:58:15.700000  4-3-2-5         705  1.517892  0.052452   0.0    4    5   \n",
       "6  00:58:28.700000  4-3-2-5         720  1.559973  0.042081   0.0    4    5   \n",
       "7  00:58:41.800000  4-3-2-5         772  3.505945  1.945972   0.0    4    5   \n",
       "8  00:58:54.800000  4-3-2-5         672  0.675440  2.830505   0.0    4    5   \n",
       "9  00:59:07.800000  4-3-2-5        1668  7.353544  6.678104   0.0    4    5   \n",
       "\n",
       "   组合  \n",
       "0  45  \n",
       "1  45  \n",
       "2  45  \n",
       "3  45  \n",
       "4  45  \n",
       "5  45  \n",
       "6  45  \n",
       "7  45  \n",
       "8  45  \n",
       "9  45  "
      ]
     },
     "execution_count": 50,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "#导入数据测试\n",
    "df2='45.xlsx'\n",
    "data2=pd.read_excel(df2)\n",
    "data2.head(10)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 99,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "[ 1.35564804  0.0616312   1.39009952 ... 41.685462   41.73803329\n",
      "  0.26869774]\n"
     ]
    }
   ],
   "source": [
    "# 创建一个Series对象\n",
    "s = data2[\"jitter\"]\n",
    "#s = data2[\"jitter\"]\n",
    "# 将Series转换为ndarray\n",
    "arr = s.to_numpy()\n",
    "# 输出数组\n",
    "print(arr)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 100,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "numpy.ndarray"
      ]
     },
     "execution_count": 100,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "type(arr)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 101,
   "metadata": {},
   "outputs": [],
   "source": [
    "import matplotlib\n",
    "import matplotlib.pyplot as plt\n",
    "\n",
    "matplotlib.rcParams['font.family'] = 'SimHei'"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 102,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "numpy.ndarray"
      ]
     },
     "execution_count": 102,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "#all_data = np.fromfile(\"ec_data\")\n",
    "all_data=arr\n",
    "type(all_data)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 103,
   "metadata": {},
   "outputs": [],
   "source": [
    "from sklearn.preprocessing import MinMaxScaler\n",
    "stand_scaler = MinMaxScaler()\n",
    "all_data = stand_scaler.fit_transform(all_data.reshape(-1,1))"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": []
  },
  {
   "cell_type": "code",
   "execution_count": 104,
   "metadata": {},
   "outputs": [],
   "source": [
    "#sequence_len = 10 #原来的\n",
    "sequence_len = 5 #最适合\n",
    "X = []\n",
    "Y = []\n",
    "for i in range(len(all_data)-sequence_len):\n",
    "    X.append(all_data[i:i+sequence_len])\n",
    "    Y.append(all_data[i+sequence_len])\n",
    "X = np.array(X)\n",
    "Y = np.array(Y)\n",
    "#这段代码的作用是将一个给定时间序列数据 `all_data` 按照指定的时间步长 `sequence_len` 进行滑窗切分，切分出一系列的样本数据，以便之后输入模型进行训练或预测。\n",
    "#具体来说，假设原始的时间序列数据为 $[x_1, x_2, ..., x_n]$，那么代码首先定义了两个空列表 `X` 和 `Y`，然后在一个 for 循环中对原始数据进行了以下处理：\n",
    "#1. 对于每个下标 `i`，从原始数据中切分出长度为 `sequence_len` 的子序列 `all_data[i:i+sequence_len]`，并将该子序列添加到 `X` 列表中；\n",
    "#2. 将切分后的子序列的下一个元素 `all_data[i+sequence_len]` 添加到 `Y` 列表中。\n",
    "#最终，`X` 和 `Y` 数组将分别包含所有通过滑窗切分得到的样本数据和对应的标签数据。其中，`X` 的形状为 `(n-sequence_len, sequence_len)`，\n",
    "#表示共有 `n-sequence_len` 个样本，每个样本有 `sequence_len` 个特征值；而 `Y` 的形状为 `(n-sequence_len,)`，表示每个样本对应一个标签（即下一个时间步的特征值）。"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 105,
   "metadata": {},
   "outputs": [],
   "source": [
    "from sklearn.model_selection import train_test_split\n",
    "X_train, X_test, Y_train, Y_test = train_test_split(X, Y, test_size=0.05)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 106,
   "metadata": {},
   "outputs": [],
   "source": [
    "import tensorflow as tf\n",
    "from tensorflow import keras\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 107,
   "metadata": {},
   "outputs": [],
   "source": [
    "from keras.models import Sequential\n",
    "from keras.layers import Dense,LSTM\n",
    "\n",
    "\n",
    "def build_model(activation_name,):\n",
    "    model = Sequential()\n",
    "    #model.add(LSTM(128, input_shape=(sequence_len,1),return_sequences=True))  #原来的\n",
    "    #model.add(LSTM(128, input_shape=(sequence_len,1),return_sequences=True))\n",
    "    #model.add(LSTM(64))\n",
    "   # model.add(Dense(1,activation=activation_name))\n",
    "    #optimizer =tf.optimizers.Adam(learning_rate=0.1) #原来的\n",
    "    optimizer =tf.optimizers.Adam(learning_rate=0.05)\n",
    "    #model.compile(loss='mean_squared_error', optimizer=optimizer, metrics=['mape'])\n",
    "    #model.compile(loss='mean_squared_error', optimizer=optimizer, metrics=['mape'])\n",
    "    \n",
    "    model.add(keras.layers.LSTM(units=32, input_shape=(None, 1)))\n",
    "    model.add(keras.layers.Dense(units=1))\n",
    "    model.compile(optimizer='adam', loss='mean_squared_error')\n",
    "    return model\n",
    "\n",
    "\n",
    "#这些代码是用来构建一个神经网络模型，主要应用于时间序列数据的预测。具体作用如下：\n",
    "#导入Keras库中的Sequential顺序模型和LSTM层\n",
    "#定义了一个函数build_model，用于构建神经网络模型\n",
    "#在模型中添加了两个LSTM层，分别为含有128个节点的输入层和含有64个节点的输出层\n",
    "#向模型添加了一个具有1个节点的稠密层(Dense)，并指定激活函数为用户提供的activation_name参数（实现可配置）\n",
    "#定义了优化器Adam，并设置学习率为0.1\n",
    "#编译了模型，指定损失函数为均方差误差（mean_squared_error），优化器为Adam，并使用平均绝对百分比误差（mean absolute percentage error）进行模型评估\n",
    "#返回构建好的模型"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 108,
   "metadata": {},
   "outputs": [],
   "source": [
    "lstm = build_model(\"sigmoid\")\n",
    "step = 250"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 109,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "(1167, 5, 1)"
      ]
     },
     "execution_count": 109,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "X_train.shape"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 110,
   "metadata": {},
   "outputs": [],
   "source": [
    "#history = lstm.fit(\n",
    "#    X_train, Y_train, epochs=50, batch_size = 32,verbose=0,validation_data = (X_test, Y_test)\n",
    "#    )\n",
    "history = lstm.fit(\n",
    "    X_train, Y_train, epochs=50, batch_size = 32,verbose=0,validation_data = (X_test, Y_test)\n",
    "    )\n",
    "\n",
    "#epochs (轮数): 整个训练集数据将被用来训练神经网络50次。\n",
    "#batch_size (批处理大小)：每个训练批次包含的样本数量为32。\n",
    "#verbose (冗长模式): 设置为0以关闭详细输出。\n",
    "#validation_data (验证数据): 将测试集作为验证数据传入，以了解模型的表现情况。\n",
    "#总体来说，lstm.fit()方法会根据提供的训练数据和超参数对模型进行训练，\n",
    "#并且返回一个 history 对象，其中包含一些有关模型表现的统计信息（例如每轮结束后的训练和验证损失、准确度等）。"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 111,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "WARNING:tensorflow:5 out of the last 11 calls to <function Model.make_predict_function.<locals>.predict_function at 0x000002139AFB79D0> triggered tf.function retracing. Tracing is expensive and the excessive number of tracings could be due to (1) creating @tf.function repeatedly in a loop, (2) passing tensors with different shapes, (3) passing Python objects instead of tensors. For (1), please define your @tf.function outside of the loop. For (2), @tf.function has reduce_retracing=True option that can avoid unnecessary retracing. For (3), please refer to https://www.tensorflow.org/guide/function#controlling_retracing and https://www.tensorflow.org/api_docs/python/tf/function for  more details.\n",
      "2/2 [==============================] - 0s 3ms/step\n"
     ]
    }
   ],
   "source": [
    "Y_predict = lstm.predict(X_test)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 112,
   "metadata": {},
   "outputs": [],
   "source": [
    "Y_predict_real = stand_scaler.inverse_transform(Y_predict.reshape(-1,1))\n",
    "Y_test_real = stand_scaler.inverse_transform(Y_test.reshape(-1,1))\n",
    "# print(Y_predict_real,Y_test_real)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 113,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "[<matplotlib.lines.Line2D at 0x213a1c1ca00>]"
      ]
     },
     "execution_count": 113,
     "metadata": {},
     "output_type": "execute_result"
    },
    {
     "data": {
      "image/png": "iVBORw0KGgoAAAANSUhEUgAABJQAAACKCAYAAAD8ORC9AAAAOXRFWHRTb2Z0d2FyZQBNYXRwbG90bGliIHZlcnNpb24zLjUuMSwgaHR0cHM6Ly9tYXRwbG90bGliLm9yZy/YYfK9AAAACXBIWXMAAAsTAAALEwEAmpwYAAA7N0lEQVR4nO3dd3hc1Z3/8feZGXXJkmzJkrtx7zbYBpsSTDUQIPQeWghJSNkN2dQfhM0GUjYklM2yAQKEUOMAofcONgZsg3vHlm3ZsiQXdWnKPb8/zowsG9keWWVG9uf1PPe59545c+eM5ujOvd85xVhrERERERERERERiZcv0QUQEREREREREZHuRQElERERERERERFpEwWURERERERERESkTRRQEhERERERERGRNlFASURERERERERE2kQBJRERERERERERaZNAogvQEQoKCuzgwYMTXQwRERERERERkYPG/PnzK621ha09dlAElAYPHsy8efMSXQwRERERERERkYOGMaZkb4+py5uIiIiIiIiIiLSJAkoiIiIiIiIiItImCiiJiHQna9+G929PdClEREREROQQp4CSiEh38sn98M5vINSY6JKIiIiIiMghTAElEZHupGwx2AhUrEh0SURERERE5BCmgJKISHfRsAOqNrrtssWJLYuIiIiIiBzSFFASEekuypa02FZASUREREREEkcBJRGR7iIWRMo/DLYu2XdeERERERGRTqSAkohId7F1CWT1hmEnudZK1ia6RCIiIiIicohSQElEpLsoWwTF46BoHDRVwc4NiS6RiIiIiIgcohRQEhHpDsJBqFgJxeOheIJL0zhKIiIiIiKSIAooiYh0B5WrIBJ0waTeo8H4NI6SiIiIiIgkjAJKIiLdQaw1UtE4SM2EXsPUQklERERERBJGASURke5g6xIIpLtAEriub2WLElsmERERERE5ZMUVUDLGPGCMmWOMuaktedqQVmSM+aDFfj9jzCZjzLvRpbDtb01E5CBStsh1dfMH3H7RODcod8POhBZLREREREQOTfsNKBljzgP81tqjgb7GmOHx5GlDWj7wMJDV4pBHAbdZa2dEl4r2v1URkW7KWihb4lolxcQG5t66NDFlEhERERGRQ1o8LZRmALOi228Dx8aZJ960CHAxUN3ieNOAG4wxHxlj7mitUMaY640x84wx8yoqFG8SkYNY9WZo2L4riARQPM6tNTC3iIiIiIgkQDwBpSygNLpdDRTFmSeuNGtttbW2ao/jvQIcba2dDowwxkzY43GstfdZa6dYa6cUFqpHnIgcxFoOyB2TXQRZhRpHSUREREREEiKegFItkBHdzt7Lc1rLE29aa+ZYa2ui2yuAL3WzExE5ZGyNBZTG7kozxgWYNNObiIiIiIgkQDwBpfns6uY2EVgfZ55401rzmjGmjzEmE5gJqE+HiBy6yhZD/mGQ3mP39OLxUL4CIqHElEtERERERA5ZgTjyPAt8YIzpC5wOXGKMudVae9M+8kwDbJxprfkV8A4QBP5irV3Z1jcmInLQKFu8a8ykloonQKQJKldD0ZiuL5eIiIiIiByy9ttCyVpbjRtMey5wgrV24R7BpNbyVMWb1uIYM1psv2OtHWWtnWCt/XO73qGISHfWVAPb1+0+IHeMBuYWEREREZEEiafLG9baHdbaWdbasrbkiTdNRET2YusywO4+IHdMr+HgT9PA3CIiIiIi0uXiCiiJiEiCxAbkLh7/5cf8Aeg9GsrUQklERERERLqWAkoiIsmsbDGk50Fu/9YfLx7v8ljbpcUSEREREZFDmwJKIiLJrGyxCxoZ0/rjxeOhvhJq1ItYRERERES6jgJKIiLJyou4MZRa6+4WE3tMA3OLiIiIiEgXUkBJRCRZbVsL4YbWB+SOKRrr1hqYW0REREREupACSiIiySoWJNpXC6X0XMgbpIG5RURERESkSymgJCKSrLYuAV8KFI7ad77YwNwiIiIiIiJdRAElEZFkVbYYCkdCIHXf+YrHw7Y1EKzrmnKJiIiIiMghTwElEZFkVbZk393dYorHAxbKl3d6kUREREREREABJRGR5FRbDrVl8QWUYoN2a2BuERERERHpIgooiYgko9iYSPua4S0mbyCk5WpgbhERERER6TIKKImIJKOt0eBQPC2UjIHicRqYW0REREREuowCSiIiyahsMfToB5k948tfPB62LgXP69xyiYiIiIiIoICSiEhyindA7pji8RCqgx3rOq9MIiIiIiIiUQooiYgkm1ADVK5qW0CpeWBudXsTEREREZHOp4CSiEiyKV8ONhLfgNwxhaPAF1BASUREREREukRcASVjzAPGmDnGmJvakqcNaUXGmA9a7KcYY16M5ru27W9LRKQba8uA3DEp6VAwQgElERERERHp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",
      "text/plain": [
       "<Figure size 1440x144 with 1 Axes>"
      ]
     },
     "metadata": {
      "needs_background": "light"
     },
     "output_type": "display_data"
    }
   ],
   "source": [
    "fig = plt.figure(figsize=(20, 2))\n",
    "plt.plot(Y_predict_real/(1024*1024))\n",
    "plt.plot(Y_test_real/(1024*1024))\n",
    "#其中figsize参数用于设置图形窗口的大小。\n",
    "#对于Y_predict_real和Y_test_real进行归一化处理，将返回的结果转换为单位为MB（兆字节），即除以1024*1024"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 114,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "根均方误差(RMSE)：2.090747094419617e-05\n",
      "平均绝对百分比误差(MAPE)：2.047230983730555\n"
     ]
    }
   ],
   "source": [
    "def MAPE(true, pred):\n",
    "    diff = np.abs(np.array(true) - np.array(pred))\n",
    "    return np.mean(diff / true)\n",
    "def RMSE(predictions, targets):\n",
    "    return np.sqrt(((predictions - targets) ** 2).mean())\n",
    "\n",
    "print(f\"根均方误差(RMSE)：{RMSE(Y_predict_real/(1024*1024), Y_test_real/(1024*1024))}\")\n",
    "print(f\"平均绝对百分比误差(MAPE)：{MAPE(Y_predict, Y_test)}\")"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 115,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "程序运行时间:16703.125毫秒\n"
     ]
    }
   ],
   "source": [
    "T2 =time.process_time()\n",
    "print('程序运行时间:%s毫秒' % ((T2 - T1)*1000))\n",
    "# 系统: Windows\n",
    "# 程序运行时间:-毫秒"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": []
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": []
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": []
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": []
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": []
  }
 ],
 "metadata": {
  "kernelspec": {
   "display_name": "Python 3",
   "language": "python",
   "name": "python3"
  },
  "language_info": {
   "codemirror_mode": {
    "name": "ipython",
    "version": 3
   },
   "file_extension": ".py",
   "mimetype": "text/x-python",
   "name": "python",
   "nbconvert_exporter": "python",
   "pygments_lexer": "ipython3",
   "version": "3.9.2"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 2
}
